        TITL DAI FIRMWARE D790-D8FA  V1.1
        ORG   :D790
*
*
*
************************
* CHECK FREE RAM SPACE *
************************
*
* Entry: DE: Startaddress.
*        HL: 1st not useable address.
* Exit:  HL: Useable RAM space.
*        ABCDE preserved.
*
MPT25   CALL  :DE1A     Calculate free space
        DCX   H
        RET
*
**********************************
* TRANSFER DATA/CASSETTE VECTORS *
**********************************
*
* Transfer data/cassette switching vectors from
* ROM to RAM vector area.
*
* Exit: AFBC preserved. DEHL corrupted.
*
*MPT01
CASIN   PUSH  B
        LXI   H,:D7CB   Highest source address
        LXI   D,:D7A4   Lowest source address
        LXI   B,:02C5   Lowest destination address
        CALL  :DE4F     Transfer cassette vectors
        POP   B
        RET
*
***********************************
* DATA/CASSETTE SWITCHING VECTORS *
***********************************
*
* This data block is moved into the RAM area
* #02C5-#02EB during system initialisation.
*
CINTB   JMP   :D2B8     WOPEN
        JMP   :D2F1     WBLK
        JMP   :D427     WCLOSE
        JMP   :D325     ROPEN
        JMP   :D340     RBLK
        JMP   :D445     RCLOSE
        JMP   :D3A2     MBLK
        RET             RESET
        NOP
        NOP
        RET             DOUTC
        NOP
        NOP
        JMP   :DDB4     DINC
        RET
        NOP
        NOP
        DATA  :24,:24   TAPSL
        DATA  :24,:3C   TAPSD
        DATA  :24,:18   TAPST
*
************************************
* WAIT FOR SPACEBAR, PRINT CAR.RET *
************************************
*
* Exit: BCDEHL preserved.
*       CY=1: Break pressed.
*
*CINTE
WPT     CALL  :D6DA     Wait for spacebar
        JC    :C80C     If BREAK pressed: into
 REM Basic monitor
        JMP   :DD5E     Print car.ret; ret
*
        DATA  :FF
        DATA  :FF
        DATA  :FF
        DATA  :FF
*
*********************************
* WRITE BLOCK + TRAILER ON TAPE *
*********************************
*
* Entry: DE: Length block.
*        HL: Startaddress block.
* Exit:  A=0, BCDE preserved.
*        HL points past block written.
*
MPT10   CALL  :02C8     Write block
        JMP   :02CB     Write trailer
*
************************
* FAILURE DURING ROPEN *
************************
*
RPN20   DCR   C
        INR   C         Load during program ?
        CNZ   :DD5E     Print car.ret if not
        JMP   :D329     Back to read file leader
*
*****************************
* PRINT MESSAGE ON NEW LINE *
*****************************
*
* New routine. It moves the cursor to a new line
* before a message is printed. Used for printing
* 'STOPPED IN LINE ...' and 'END PROGRAM'.
*
        CALL  :DD55     ] Cursor to column 0
        JMP   :DAFF     ] Print message
*
*****************
* FAST PRINTING *
*****************
*
* Instruction only moved.
*
        PUSH  H
        LHLD  :0072     Get cursor position address
        MOV   M,A       Write byte on screen
        DCX   H         ) Update cursor addr
        DCX   H         )
        SHLD  :0072     Save new cursor address
        POP   H
        RET
*
***************************
* SAVE: WRITE NAME LENGTH *
***************************
*
* Entry: HL: Addr. length byte of name.
* Exit:  DE: Length of name.
*        HL: Points past string.
*        BC: Preserved.
*        A:  Checksum on string.
*
MPT22   MOV   E,M       Get name length
        MVI   D,:00
        INX   H         HL to 1st byte of name
        JMP   :D2F1     Write name length
*
********************************
* INITIALISE LOADING FROM TAPE *
********************************
*
* Entry: HL: Points to length byte of name requested
* Exit:  DE: Length requested name.
*        HL: Points to first byte of name.
*        AFBC preserved.
*
MPT23   MOV   E,M       Get length requested name
        MVI   D,:00     in DE
        INX   H         HL points to 1st byte name
        JMP   :D42E     Cassette motors on; ret
*
*********************
* UPDATE POROM/PORO *
*********************
*
* Entry: MPT52: Byte for ROM/cassette select in A.
*        MPT53: New POROM byte.
*
MPT52   ANI   :F0       Enable ROM/cassette select
MPT53   STA   :0040     Load POROM
        STA   :FD06     and PORO
        RET
*
*****************
* part of 2EAC1 *
*****************
*
* If pointer is off top visible screen:
*
PCK40   MOV   A,D
        CPI   :D0
        JC    :EAEF     (2) if <= CF (no overflow
 REM below 0)
        PUSH  H         ) if > CF:
        PUSH  B         ) Exchange BC and HL
        POP   H         )
        POP   B         )
        JMP   :EAEF     (2)
*
        DATA  :FF
*
**********************
* RUN basiccmd SAVEA *
**********************
*
RSAVA   CALL  :D83B     Evaluate array type to be
 REM saved
        PUSH  PSW       Save type array
        JNZ   :D826     Jump if INT/FPT array
        RST   4         Move stringarray into one
        DATA  :75       string in free RAM
LD99    POP   PSW       Get type array
        PUSH  H
        PUSH  D
        PUSH  PSW
        CALL  :E791     (0) Evaluate program name
        MVI   A,:32     File type byte '2'
        CALL  :02C5     WOPEN
        POP   PSW       Get type array
        LXI   H,:013E   Startaddr EBUF
        MOV   M,A       Type into EBUF
        JMP   :D668     Write 2 blocks + trailer
*
        NOP
*
******************************************
* EVALUATE ARRAY TYPE TO BE SAVED/LOADED *
******************************************
*
* Exit: A:   Array type.
*       DE:  Length all array elements.
*       HL:  Beginaddr. 1st array element.
*       Z=1: String array.
*       Z=0: INT/FPT array.
*
RLSAS   CALL  :E95A     (0) Get array addr in HL
        ANI   :30       Allow any type array
        PUSH  PSW       Save type
        MOV   E,M       )
        INX   H         ) Get array pntr in DE
        MOV   D,M       )
        MOV   A,E
        ORA   D
        JZ    :E990     (0) Undef. array if no addr
        XCHG            Pointer to array in HL
        DCX   H
        DCX   H
        MOV   D,M       Get 1st length byte
        INX   H
        MOV   A,M       Get 2nd length byte
        INX   H
        SUB   M         Minus nr of dim. bytes
        MOV   E,A
        MOV   A,D
        SBI   :00       Update hibyte if borrow
        MOV   D,A
        DCX   D         DE is length all array elem.
        CALL  :DE39     HL is beginaddr 1st element
        POP   PSW       Get type in A
        CPI   :20       Set Z-flag on type
        RET
*
**********************
* RUN basiccmd LOADA *
**********************
*
RLODA   CALL  :D83B     Evaluate array type to be
 REM loaded
        PUSH  H         Save startaddr array elem.
        PUSH  PSW       Save type
        CALL  :D678     Evaluate requested program
 REM name; prep. select ROM bank
        CALL  :D808     Select ROM bank 1
        POP   PSW       Get type
        JMP   :EE0F     (1) Read block from tape and
 REM store it in array
*
************************************
* INITIALISE 'EDIT': EMPTY HEAP,   *
* CLEAR SYMBOL TABLE, MOVE PROGRAM *
************************************
*
* Part of 'Init. EDIT' (0E265).
*
* Entry: CY=1: Not sufficient memory available.
*
MPT33   JC    :DA10     Evt. run error 'OUT OF
 REM MEMORY'
        JMP   :CB23     Empty heap, move
 REM program, clear symtab
*
******************************************
* LIST CURRENT LINE IF LINENR IS CORRECT *
******************************************
*
* Part of 'run LIST <range>' (0E1B6).
*
* Entry: CY=0 if linenr. <= 0 or > FFFF.
*
MPT3A   JNC   :DA15     Evt. run error 'NUMBER
 REM OUT OF RANGE'
        JMP   :ECAB     (0) List current line
*
**************************
* INPUT FROM EDIT BUFFER *
**************************
*
* Part of 'restart interpreter' (C823).
*
MPT05   PUSH  H
        CALL  :E291     (0) Input from editbuffer
        POP   H
        RET
*
*******************************
* part of RUN 'CLEAR' (0E6B5) *
*******************************
*
* Checks for heap too big.
*
MPT42   POP   H         ] Get difference
        DAD   B         ] Add textpntr
        MOV   B,H       ] New textpntr in BC
        MOV   C,L       ]
        ORA   A         ] No special action
        RET             ]
        DATA  :FF       ]
*
************************************
* EVT. INITIALISE 4 COLOUR ANIMATE *
************************************
*
* Part of 2E9C3.
*
SPT04   CPI   :14
        RNC             Abort if A >= 14
        STA   :00C1     Set for 4-colour animate
        RET
*
********
* DATA *
********
*
LD221   DATA  :20       Space
        DATA  :8C,:72   Pntr. to 'MODE'
        DATA  :00
*
******************************
* part of 1EE0B - (not used) *
******************************
*
LD105   PUSH  PSW
        CALL  :E791     (1)
        POP   PSW
        RET
*
*******************************************
* READ BLOCK FROM TAPE, EVT. ERROR REPORT *
*******************************************
*
* Part of LOADA (1EE0F).
*
MPT19   CALL  :02D1     Read block from tape
*
************************
* READ BLOCK FROM TAPE *
************************
*
* Now cassette motors are switched off directly
* after reading is finished.
* Especially in LOADA, switching off the cassette
* motors after re-arranging all data was very
* annoying.
*
        JMP   :D265     Evt. run 'LOADING ERROR'
        RET
*
**************************************
* LIST ARRAY NAME, SPACE, EXPRESSION *
**************************************
*
* Used in listing 'Savea/Loada' textlines.
*
SCN30   CALL  :EEF7     (0) List array name
        JMP   :ED65     (0) List space, expression
*
        DATA  :FF
        DATA  :FF
*
******************************
* INITIALISE SOUND GENERATOR *
******************************
*
* All sound channels are switched off.
*
* Exit: AB preserved, CDEHLF corrupted.
*
SNDINI  LXI   H,:FC06
        MVI   M,:36     ) Load 3 timers
        MVI   M,:76     )
        MVI   M,:B6     )
        LXI   H,:0000
        SHLD  :FD04     Volume 4 channels off
        SHLD  :0294     and remember it
        LXI   H,:01C2   Start 1st SCB
        LXI   D,:000E   Length SCB
        MVI   C,:04     4 blocks (3 SCB, 1 NCB)
SNI10   MVI   M,:FF     FF in 1st byte SCB (= off)
        DAD   D         Calc start next block
        DCR   C
        JNZ   :D8C0     Next block if not ready
        RET
*
*********************
* OUTPUT TO DCE-BUS *
*********************
*
* 'Real World' output. Writes a byte to a given
* Real World address.
*
* Entry: D: Busaddress.
*        E: Data for output.
*
RWOP    PUSH  PSW
        PUSH  H
        LXI   H,:FE03   GIC control address
        MVI   M,:80     All ports output
        DCX   H         Port C addr. in HL
        MVI   M,:FE     Clear bus expand signal
        XCHG            Data in L, busaddr. in H
        SHLD  :FE00     Data in PA, busaddr. in PB
        XCHG            Address PC in HL
        INR   M         Set bus expand signal
        MVI   M,:FD     Set write strobe true
 REM (Now data exchange done)
        MVI   M,:FF     Reset strobe
        DCR   M         Clear bus expand signal
        POP   H
        POP   PSW
        RET
*
**********************
* INPUT FROM DCE-BUS *
**********************
*
* 'Real World' input. Reads a byte from a given
* Real World address.
*
* Entry: D: Busaddress.
* Exit:  E: Data received.
*
RWIP    PUSH  PSW
        PUSH  H
        LXI   H,:FE03   GIC control addr. in HL
        MVI   M,:90     PA input, rest output
        DCX   H         Address PC in HL
        MVI   M,:FE     Clear bus expand signal
        MOV   A,D       Busaddress in A
        STA   :FE01     Store busaddress in PB
        INR   M         Set bus expand signal
        MVI   M,:FB     Set read strobe true
 REM (Now data exchange)
        LDA   :FE00     Data to A
        MOV   E,A       Data in E
        MVI   M,:FF     Reset strobe
        DCR   M
        POP   H
        POP   PSW
        RET
*
*
*
        UNL
CINTE   EQU WPT
MPT01   EQU CASIN
        LST
        END
